#!/usr/bin/env python
"""
找到任意目录树里所有给定类型的文件里最大的那个。
避免重复路径，捕获错误，添加追踪和行数大小。
同样使用集合、文件迭代器和生成器以避免装在整个文件。
并试图绕过不可解码的目录/文件名称的打印。
"""

import os
import pprint
import sys


def tryprint(text):
    try:
        print(text)
    except UnicodeEncodeError:
        print(text.encode)


def getFromCommand():
    returnVar = [os.curdir, '.py', 1]
    if len(sys.argv) > 1:
        returnVar[0] = sys.argv[1]
        if len(sys.argv) > 2:
            returnVar[1] = sys.argv[2]
            if len(sys.argv) > 3:
                returnVar[2] = int(sys.argv[3])
    return returnVar


def getFileList(curdir, files, extname, allsizes, trace):
    for file in files:
        if file.endswith(extname):
            if trace > 1:
                tryprint('\t' + file)
            fullpath = os.path.join(curdir, file)

            try:
                size = os.path.getsize(fullpath)
                numlines = sum(+1 for line in open(fullpath, 'rb'))
            except Exception:
                print('error', sys.exc_info[0])
            else:
                allsizes.append((size, numlines, fullpath))


def getAllSizes(dirname, extname, trace):
    visited = set()
    allsizes = []

    for curdir, subdir, files in os.walk(dirname):
        if trace:
            tryprint(curdir)
        curdir = os.path.normpath(curdir)

        if sys.platform[:3] == 'win':
            fixname = os.path.normcase(curdir)
        else:
            fixname = curdir

        if fixname in visited:
            if trace:
                tryprint('skipping ' + curdir)
        else:
            visited.add(curdir)

            getFileList(curdir, files, extname, allsizes, trace)

    allsizes.sort()
    return allsizes


def showResult(allsizes):
    for title, key in (('bytes', 0), ('lines', 1)):
        print('\nBy {}...'.format(title))
        allsizes.sort(key=lambda x: x[key])
        pprint.pprint(allsizes[:3])
        pprint.pprint(allsizes[-3:])


def bigextTree(
    command=True, show=True, dirname=os.curdir, extname='.py', trace=1
):
    if command:
        [dirname, extname, trace] = getFromCommand()

    allsizes = getAllSizes(dirname, extname, trace)
    if show:
        showResult(allsizes)


if __name__ == '__main__':
    bigextTree()
